package com.cman777.springc.common.helper.jacksonkeydeserializer;

import com.cman777.springc.common.bean.Iface.EnumIFace;
import com.cman777.springc.common.bean.exception.BusinessException;
import com.cman777.springc.common.helper.GenericUtil;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.KeyDeserializer;
import com.fasterxml.jackson.databind.deser.ContextualKeyDeserializer;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.math.BigDecimal;

/**
 * @author chenzhicong
 * @time 2020/6/24 13:47
 */
public class EnumKeyDeserializer<T extends EnumIFace> extends KeyDeserializer implements ContextualKeyDeserializer {
    private Class<T> targetClass = null;

    public EnumKeyDeserializer() {
    }

    public EnumKeyDeserializer(Class<T> targetClass) {
        this.targetClass = targetClass;
    }
    @Override
    public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException {
        String valueStr = key;
        if (StringUtils.isBlank(valueStr)) {
            return null;
        }
        if(!EnumIFace.class.isAssignableFrom(targetClass)){
            return valueOfEnumName(targetClass,valueStr);
        }
        Object val = null;
        Class codeType = GenericUtil.getGenericClass(targetClass, 1);
        if(String.class.isAssignableFrom(codeType)){
            val = String.valueOf(valueStr);
        }
        if(Integer.class.isAssignableFrom(codeType)){
            val = Integer.valueOf(valueStr);
        }
        if(BigDecimal.class.isAssignableFrom(codeType)){
            val = new BigDecimal(valueStr);
        }
        if(Long.class.isAssignableFrom(codeType)){
            val = new Long(valueStr);
        }
        return valueOf(targetClass, val);
    }

    @Override
    public KeyDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException {
        Class<T> targetClass = (Class<T>) ctxt.getContextualType().getRawClass();
        return new EnumKeyDeserializer(targetClass);
    }
    private T valueOf(Class<T> enumClass, Object val) {
        T[] enumConstants = enumClass.getEnumConstants();
        if (null != enumConstants) {
            for (T e : enumConstants) {
                if (e.getCode().equals(val)) {
                    return e;
                }
            }
            throw new BusinessException("ENUM_NOT_EXIST", enumClass.getSimpleName() + "枚举中没有" + val);
        }
        return null;
    }
    private T valueOfEnumName(Class<T> enumClass, String val) {
        T[] enumConstants = enumClass.getEnumConstants();
        if (null != enumConstants) {
            for (T e : enumConstants) {
                Enum em =  (Enum)e;
                if (em.name().equals(val)) {
                    return e;
                }
            }
            throw new BusinessException("ENUM_NOT_EXIST", enumClass.getSimpleName() + "枚举中没有" + val);
        }
        return null;
    }
}
